package io.esir.permission;

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;

import java.util.Arrays;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.core.app.AppOpsManagerCompat;
import androidx.core.content.ContextCompat;
import io.esir.permission.target.AppActivityTarget;
import io.esir.permission.target.AppFragmentTarget;
import io.esir.permission.target.ContextTarget;

/**
 * Utility class for access to runtime permissions.
 * App 权限
 * Created by Huangrc on 2017/10/23.
 */

public class AppPermission {

    /**
     * 是不是已获取指定的权限
     *
     * @param context     上下文
     * @param permissions 权限
     * @return true 获取了指定的全部权限，false 没有获取权限（全部，或部分）
     */
    public static boolean hasPermission(@NonNull Context context, @NonNull String... permissions) {
        return hasPermission(context, Arrays.asList(permissions));
    }
    /**
     * 是不是已获取指定的权限
     *
     * @param context     上下文
     * @param permissions 权限
     * @return true 获取了指定的全部权限，false 没有获取权限（全部，或部分）
     */
    public static boolean hasPermission(@NonNull Context context, @NonNull List<String> permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }
        for (String permission : permissions) {
            int result = ContextCompat.checkSelfPermission(context, permission);
            if (result == PackageManager.PERMISSION_DENIED) {
                return false;
            }
            String op = AppOpsManagerCompat.permissionToOp(permission);
            if (TextUtils.isEmpty(op)) {
                continue;
            }
            result = AppOpsManagerCompat.noteProxyOp(context, op, context.getPackageName());
            if (result != AppOpsManagerCompat.MODE_ALLOWED) {
                return false;
            }
        }
        return true;
    }

    /**
     * Some privileges permanently disabled, may need to set up in the execute.
     *
     * @param activity          {@link Activity}.
     * @param deniedPermissions one or more permissions.
     * @return true, other wise is false.
     */
    public static boolean hasAlwaysDeniedPermission(@NonNull Activity activity, @NonNull List<String> deniedPermissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return false;
        }

        if (deniedPermissions.size() == 0) {
            return false;
        }

        for (String permission : deniedPermissions) {
            boolean rationale = activity.shouldShowRequestPermissionRationale(permission);
            if (!rationale) {
                return true;
            }
        }
        return false;
    }

    /*/**
     * Some privileges permanently disabled, may need to set up in the execute.
     *
     * @param fragment          {@link android.support.v4.app.Fragment}.
     * @param deniedPermissions one or more permissions.
     * @return true, other wise is false.
     *//*
    public static boolean hasAlwaysDeniedPermission(
            @NonNull android.support.v4.app.Fragment fragment,
            @NonNull List<String> deniedPermissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return false;
        }

        if (deniedPermissions.size() == 0) {
            return false;
        }

        for (String permission : deniedPermissions) {
            boolean rationale = fragment.shouldShowRequestPermissionRationale(permission);
            if (!rationale) {
                return true;
            }
        }
        return false;
    }*/

    /**
     * Some privileges permanently disabled, may need to set up in the execute.
     *
     * @param fragment          {@link android.app.Fragment}.
     * @param deniedPermissions one or more permissions.
     * @return true, other wise is false.
     */
    public static boolean hasAlwaysDeniedPermission(
            @NonNull android.app.Fragment fragment,
            @NonNull List<String> deniedPermissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return false;
        }

        if (deniedPermissions.size() == 0) {
            return false;
        }

        for (String permission : deniedPermissions) {
            boolean rationale = fragment.shouldShowRequestPermissionRationale(permission);
            if (!rationale) {
                return true;
            }
        }
        return false;
    }

    /**
     * Some privileges permanently disabled, may need to set up in the execute.
     *
     * @param context           {@link Context}.
     * @param deniedPermissions one or more permissions.
     * @return true, other wise is false.
     */
    public static boolean hasAlwaysDeniedPermission(
            @NonNull Context context,
            @NonNull List<String> deniedPermissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return false;
        }

        if (deniedPermissions.size() == 0) {
            return false;
        }

        if (!(context instanceof Activity)) {
            return false;
        }

        for (String permission : deniedPermissions) {
            boolean rationale = ((Activity) context).shouldShowRequestPermissionRationale(permission);
            if (!rationale) {
                return true;
            }
        }
        return false;
    }

    /**
     * Get default setting dialog.
     *
     * @param activity    {@link Activity}.
     * @param requestCode requestCode for {@code startActivityForResult(Intent, int)}.
     * @return {@link SettingDialog}.
     */
    public static
    @NonNull
    SettingDialog defaultSettingDialog(@NonNull Activity activity, int requestCode) {
        return new SettingDialog(activity, new SettingExecutor(new AppActivityTarget(activity), requestCode));
    }

    /**
     * Get default setting dialog.
     *
     * @param context {@link Context}.
     * @return {@link SettingDialog}.
     */
    public static
    @NonNull
    SettingDialog defaultSettingDialog(@NonNull Context context) {
        return new SettingDialog(context, new SettingExecutor(new ContextTarget(context), 0));
    }

    /**
     * In the Activity.
     *
     * @param activity {@link Activity}.
     * @return {@link Request}.
     */
    public static
    @NonNull
    Request with(@NonNull Activity activity) {
        return new DefaultRequest(new AppActivityTarget(activity));
    }

    public static
    @NonNull
    Request with(@NonNull Fragment fragment) {
        return new DefaultRequest(new AppFragmentTarget(fragment));
    }

    /*public static
    @NonNull
    Request with(@NonNull android.support.v4.app.Fragment fragment) {
        return new DefaultRequest(new SupportFragmentTarget(fragment));
    }*/

    /**
     * Anywhere..
     *
     * @param context {@link Context}.
     * @return {@link Request}.
     */
    public static
    @NonNull
    Request with(@NonNull Context context) {
        return new DefaultRequest(new ContextTarget(context));
    }

    private AppPermission() {
    }
}
